import {Component, OnInit, signal} from '@angular/core';
import {UserDetailComponent, UserDetailEvent, UserDetailUpdateEvent} from "./user-detail/user-detail.component";
import {RouterLink, RouterOutlet} from "@angular/router";
import {NzColDirective, NzRowDirective} from "ng-zorro-antd/grid";
import {UserListComponent} from "./user-list/user-list.component";
import {NzContentComponent, NzHeaderComponent, NzLayoutComponent, NzSiderComponent} from "ng-zorro-antd/layout";
import {NzIconDirective} from "ng-zorro-antd/icon";
import {NzMenuDirective, NzMenuItemComponent, NzSubMenuComponent} from "ng-zorro-antd/menu";
import {NzTooltipDirective} from "ng-zorro-antd/tooltip";
import {NzButtonComponent} from "ng-zorro-antd/button";
import {BehaviorSubject, combineLatest, map, Observable, scan, switchMap} from "rxjs";
import {User} from "../@core/data/user";
import {ActionTypes, UserEvent, UserUpdateEvent} from "../user/user-table/data.t";
import {UserService} from "../user/user.service";
import {AsyncPipe} from "@angular/common";

interface ConcatUsersEvent extends UserEvent {
  type: ActionTypes.CONCAT,
}

@Component({
  selector: 'app-user-info',
  standalone: true,
  imports: [
    UserDetailComponent,
    NzRowDirective,
    NzColDirective,
    UserListComponent,
    NzContentComponent,
    NzHeaderComponent,
    NzIconDirective,
    NzLayoutComponent,
    NzMenuDirective,
    NzMenuItemComponent,
    NzSiderComponent,
    NzSubMenuComponent,
    NzTooltipDirective,
    RouterLink,
    RouterOutlet,
    NzButtonComponent,
    AsyncPipe
  ],
  templateUrl: './user-info.component.html',
  styleUrl: './user-info.component.css'
})
export class UserInfoComponent implements OnInit {
  private readonly aaa = signal<UserDetailEvent>({
    type: "init"
  })
  realNameSource = new BehaviorSubject<string>('')
  private pageNumberSource = new BehaviorSubject<number>(1);
  private pageSizeSource = new BehaviorSubject<number>(10);
  private userEventSource = new BehaviorSubject<UserEvent>({
    type: ActionTypes.INIT,
  })
  private remoteUsers$ = combineLatest([this.pageNumberSource, this.pageSizeSource, this.realNameSource])
    .pipe(
      map(([pageNumber, pageSize, realName]) => ({pageNumber, pageSize, realName})),
      switchMap(({pageNumber, pageSize, realName}) => {
        return this.userService.getUserList(
          {realName: realName},
          pageNumber,
          pageSize
        ).pipe(
          map(res => {
            return res.content
          })
        )
      })
    )
  users$!: Observable<User[]>

  constructor(private userService: UserService) {
  }

  ngOnInit(): void {
    this.remoteUsers$.subscribe((users: User[]) => {
      // 远端数据来的时候，合并数据到 users$
      this.userEventSource.next({
        type: ActionTypes.CONCAT,
        users: users
      })
    })
    this.users$ = this.userEventSource
      .pipe(
        scan((acc: User[], cur: UserEvent) => {
          return this.processUsers(acc, cur)
        }, [] as User[])
      )
  }

  processUsers(acc: User[], userEvent: UserEvent) {
    console.log('processUsers', userEvent)
    if (userEvent.type == ActionTypes.INIT) {
      return []
    }
    switch (userEvent.type) {
      case ActionTypes.CONCAT:
        let {users} = userEvent as ConcatUsersEvent
        // 如果acc为空说明是第一次加载
        if (!acc)
          return users!
        return [...acc, ...users!]
      case ActionTypes.UPDATE_USER:
        // 修改用户
        let {user} = userEvent as UserUpdateEvent
        return acc.map((oldUser) => oldUser.id === user.id ? user : oldUser)
      default:
        return acc
    }
  }

  userInfoChange(userDetailEvent: UserDetailEvent) {
    if (userDetailEvent.type == 'update') {
      let {user} = userDetailEvent as UserDetailUpdateEvent
      let updateUserEvent = {
        type: ActionTypes.UPDATE_USER,
        user: user
      } as UserUpdateEvent
      this.userEventSource.next(updateUserEvent)
    }
  }

  /**
   * 滚轮致页码变化
   */
  pageNumberChange() {
    this.pageNumberSource.next(this.pageNumberSource.value + 1)
  }

  /**
   * 姓名搜索框发生变化
   */
  realNameChange(realName: string) {
    this.resetUsers()
    this.realNameSource.next(realName)
    this.pageNumberSource.next(1)
    this.pageSizeSource.next(10)
  }

  private resetUsers() {
    this.userEventSource.next({
      type: ActionTypes.INIT,
    })
  }

}
